#include "pch.hpp"
#include "MouseHookHelper.hpp"

#include <boostext/smart_ptr.hpp>




// That is the ONLY instance of the MouseHookHelper class
// If anyone (especially myself) creates a second one, the
// application will crash and slap the programmer.
// That instance however is created lazy, meaning that the hook
// is installed when the first MouseHook is created and uninstalled
// when there are no more MouseHook instances
boostext::smart_ptr<MouseHookHelper> m_mouseHook;




MouseHookHelper::MouseHookHelper()
	: Hook(&mouseHook)
{}
///////////////////////////////////////////////////////////////////////////////////////////////////

MouseHookHelper::~MouseHookHelper()
{}
///////////////////////////////////////////////////////////////////////////////////////////////////




LRESULT MouseHookHelper::mouseProc(int nCode, WPARAM wParam, LPARAM lParam) const
{
	// "If code is less than zero, the hook procedure must pass the message to the CallNextHookEx function
	// without further processing and should return the value returned by CallNextHookEx."
	// MSDN - http://msdn.microsoft.com/en-us/library/ms644988(VS.85).aspx
	if(nCode == HC_ACTION)
	{
		foreach(const MouseHook *hook, m_hooks)
		{
			// Apply the optional filter: if the window is set, only dispatch
			// a message if it's supposed to be to this window
			PMOUSEHOOKSTRUCT msg = (PMOUSEHOOKSTRUCT)lParam;
			HWND window          = hook->window();

			if(!window || window == msg->hwnd)
				hook->mouseProc(wParam, lParam);
		}
	}

	// It is advised to always return CallNextHookEx, and not what windowProc actually
	return CallNextHookEx(m_hookHandle, nCode, wParam, lParam);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

LRESULT MouseHookHelper::mouseHook(int nCode, WPARAM wParam, LPARAM lParam)
{
	// The pointer throws on its own when it's empty
	return m_mouseHook->mouseProc(nCode, wParam, lParam);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
